package com.software.levelupserver.service.impl;


import com.software.levelupserver.entity.Badge;
import com.software.levelupserver.entity.Grade;
import com.software.levelupserver.entity.SecurityUserDetails;
import com.software.levelupserver.entity.User;
import com.software.levelupserver.exception.BizException;
import com.software.levelupserver.mappers.BadgeMapper;
import com.software.levelupserver.mappers.GradeMapper;
import com.software.levelupserver.mappers.UserMapper;
import com.software.levelupserver.service.UserService;
import com.software.levelupserver.utils.DateUtil;
import com.software.levelupserver.utils.GradeUtil;
import com.software.levelupserver.utils.JavaMailUtil;
import com.software.levelupserver.utils.UploadUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private BadgeMapper badgeMapper;
    @Resource
    private GradeMapper gradeMapper;
    @Resource
    private JavaMailUtil javaMailUtil;

    @Override
    public User getUserByEmail(String email) {
        User user = userMapper.getUserByEmail(email);
        return user;
    }

    public void getCodeForRegister(String mail){
        User userByEmail = userMapper.getUserByEmail(mail);
        if(userByEmail != null){
            throw new BizException("该邮箱已注册！");
        }
        javaMailUtil.sendCode(mail);
    }

    public String getCodeForUpdatePassword(String mail){
        User userByEmail = userMapper.getUserByEmail(mail);
        if(userByEmail == null){
            throw new BizException("该邮箱未注册！");
        }

        javaMailUtil.sendCode(mail);
        return "发送成功！";
    }

    @Override
    @Transactional
    public User registerUser(User user,String code) {
        Boolean verifyResult = verifyCode(user,code);
        String password = user.getPassword();
        if(verifyResult){
            try{
                BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
                user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
                int result = userMapper.addUser(user);
                if(result != 0){
                    clearCode(user);
                }
            }catch (Exception e){
                throw new BizException(e.getMessage());
            }
        }else {
            throw new BizException("验证码错误！");
        }
        return userMapper.getUserByEmail(user.getEmail());
    }

    @Override
    public User updateUser(User user, MultipartFile multipartFile) throws IOException {
        User authentication = getAuthenticationLoginIn();
        String image = null;
        if(multipartFile != null){
            image = UploadUtil.uploadImage(multipartFile);
        }
        if(user != null){
            userMapper.updateUser(user,image);
        }

        return userMapper.findUserByUserId(authentication.getUserId());
    }

    @Transactional
    @Override
    public void updatePassword(User user,String code){
        try{
            Boolean verifyResult = verifyCode(user,code);
            String password = user.getPassword();
            if(verifyResult){
                BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
                user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
                userMapper.updatePassword(user.getPassword(), user.getEmail());
                clearCode(user);
            }else {
                throw new BizException("验证码错误！");
            }
        }catch (Exception e){
            throw new BizException(e.getMessage());
        }

    }

    @Override
    public int deleteUserById(Integer userId) {
        return userMapper.deleteUserById(userId);
    }

    /**
     * 更新用户活跃时间
     * @return
     */
    @Override
    public boolean updateUserLoginTime() {

        //TODO 在登录的时候不能调用该方法，因为此时还没有生成token，此问题待解决

        User user = getAuthentication();

        //     User user = new User();
        String nowDate = DateUtil.getNowDate("yyyy年MM月dd日");

        boolean result = false;
        if (user != null)
            result = userMapper.updateUserLoginTime(nowDate, user.getUserId());

        return result;
    }

    @Override
    public User findUserByUserId(int userId) {
        return userMapper.findUserByUserId(userId);
    }

    @Override
    public List findAllUsers(Integer pageNum, Integer pageSize) {
        return userMapper.findAllUsers((pageNum-1)*pageSize,pageSize);
    }

    /**
     * 获取当前日期活跃用户数量
     * @return
     */
    @Override
    public int countUsersByLoginTime() {

        String nowDate = DateUtil.getNowDate("yyyy年MM月dd日");

        int activeNum = userMapper.countUsersByLoginTime(nowDate);

        return activeNum;
    }

    /**
     * 获取所有用户的数量
     * @return
     */
    @Override
    public int countUsers() {
        int userNum = userMapper.countUsers();

        return userNum;
    }

    /**
     * 更新用户经验值
     * @param experience
     * @return 返回值为0（更新经验值失败），-1（升级失败），其他（升级成功）
     */
    @Override
    public int updateExperience(double experience) {
        User oldUser = getAuthenticationLoginIn();

        User user = userMapper.getUserByEmail(oldUser.getEmail());

        boolean result = false;
        int isUp = 0;

        if (user != null){
            result = userMapper.updateExperience(experience, user.getUserId());
            user.setExperience(experience);
            if (result){
                List<Badge> badgeList = badgeMapper.selectAllBadgeByUserId(user.getUserId());
                List<Grade> grades = gradeMapper.selectAllGrade();
                isUp = GradeUtil.upGrade(user, badgeList, grades);
            }
        }

        return isUp;
    }

    /**
     * 更新用户等级
     * @param gradeId
     * @return
     */
    @Override
    public User updateGrade(int gradeId) {
        User user = getAuthenticationLoginIn();

        boolean result = false;

        if (user != null) {
            result = userMapper.updateGrade(gradeId, user.getUserId());
            if (result){
                User newUser = userMapper.getUserByEmail(user.getEmail());
                System.out.println(newUser);
                return newUser;
            }
        }

        return null;
    }

    public Boolean verifyCode(User user, String code){
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        String code2 =(String)servletRequestAttributes.getAttribute(user.getEmail(), 1);
        System.out.println("code1:"+code);
        System.out.println("code2:"+code2);

        if (code.equals(code2)){
            return true;
        }else {
            return false;
        }
    }
    public void clearCode(User user){
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        servletRequestAttributes.removeAttribute(user.getEmail(),1);
    }

    private User getAuthentication(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        SecurityUserDetails securityUserDetails = (SecurityUserDetails) authentication.getPrincipal();
        User user = securityUserDetails.getUser();
        return user;
    }

    private User getAuthenticationLoginIn(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return (User) authentication.getPrincipal();
    }
}







